

namespace SharpSoft.Web
{
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Authentication;
    using Microsoft.AspNetCore.Authorization;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.AspNetCore.Http;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.AspNetCore.Mvc.ViewFeatures;
    using Microsoft.Extensions.Hosting;
    using Microsoft.Extensions.Options;
    using Newtonsoft.Json.Linq;
    using SharpSoft.Data.DAOS;

    public class AccountController : BaseController
    {
        public AccountController(IOptions<AppConfig> appconfig, IHttpContextAccessor p_accessor, IWebHostEnvironment p_env, DatabaseService p_databaseService) : base(appconfig, p_accessor, p_env, p_databaseService)
        {
        }


        /// <summary>
        /// 在派生类中重写以提供状态描述
        /// </summary>
        /// <param name="status"></param>
        /// <returns></returns> 
        protected virtual string getUserStatusMessage(int status)
        {
            return "账号已被冻结。";
        }
        /// <summary>
        /// 使用设备信息登录
        /// </summary>
        /// <param name="deviceFingerprint">设备指纹</param>
        /// <param name="token">token</param>
        /// <param name="tokenIndate">指定token有效期，超过有效期的token无法再使用，需要重新使用其他方式登录以刷新token</param>
        /// <returns></returns>
        protected async Task innerLoginDevice(string deviceFingerprint, string token, TimeSpan tokenIndate)
        {
            var adal = this.dao<AccountsDAO>();
            var uid = adal.MatchLoginDeviceToken(deviceFingerprint, token, tokenIndate, out int loginDeviceId);
            adal.UpdateDeviceLastLoginTime(loginDeviceId);
            await this.innerLogin(uid);
        }
        /// <summary>
        /// 生成设备登录的token
        /// </summary>
        /// <param name="UserId"></param>
        /// <param name="Fingerprint"></param>
        /// <returns></returns>
        protected string generateToken(int UserId, string Fingerprint)
        {
            var seed = $"{UserId}_{Fingerprint}_{DateTime.Now.Ticks}";
            return SharpSoft.Security.MD5Hash(seed);
        }
        protected void SetLoginDevice(int UserId, string DeviceType, string Fingerprint, string DeviceData, string Display)
        {
            var token = generateToken(UserId, Fingerprint);
            var adal = this.dao<AccountsDAO>();
            adal.SetLoginDevice(UserId, DeviceType, Fingerprint, DeviceData, Display, token);
        }
        /// <summary>
        /// 使用账号密码登录
        /// </summary> 
        protected async Task innerLogin(string username, string password, string schema = null)
        {
            var pwd_md5 = Security.MD5Hash(password);
            await this.innerLoginMD5(username, pwd_md5,schema);
        }


        /// <summary>
        /// 使用MD5登录
        /// </summary> 
        protected async Task innerLoginMD5(string username, string pwd_md5, string schema = null)
        {
            AccountsDAO dal = new AccountsDAO(db, UserId);
            var id = dal.MatchPassword(username, pwd_md5);
            if (id.HasValue)
            {
                await innerLogin(id.Value,schema);
            }
            else
            {//用户不存在或密码不正确
                throw new Exception("用户不存在或密码不正确。");
            }
        }
        /// <summary>
        /// 直接使用id使用户登录
        /// </summary>
        /// <param name="uid"></param>
        /// <returns></returns>
        protected async Task innerLogin(int uid, string schema = null)
        {
            AccountsDAO dal = new AccountsDAO(db, UserId);
            var status = dal.GetUserStatus(uid);
            if (status < 0)
            {
                throw new Exception("您的账号状态异常:" + getUserStatusMessage(status));
            }
            var user = GetAppUserFromDatabase(uid);
            await this.HttpContext.SignInAsync(user, new AuthenticationProperties(), schema);
        }
        /// <summary>
        /// 注销
        /// </summary>
        protected SignOutResult innerLogout(params string[] schemas)
        {
            var result= base.SignOut(schemas);
            return result;
        }
        /// <summary>
        /// 获取或设置身份验证是否持久保存(不持久保存的Cookie在关闭浏览器后即会失效，持久保存的cookie在下次打开浏览器时依然有效)
        /// </summary>
        protected bool CookieIsPersistent { get; set; } = true;


        /// <summary>
        /// 从数据库获取用户信息
        /// </summary>
        /// <param name="uid"></param>
        /// <param name="dal"></param>
        /// <param name="permissionService"></param>
        /// <returns></returns>
        protected AppUser GetAppUserFromDatabase(int uid)
        {
            var adal = this.dao<AccountsDAO>();

            var u = adal.GetUser(uid);
            AppUser user = new AppUser(u);

            var roles = adal.GetUserRoles(user.UserId);
            List<int> ids = new List<int>();
            if (roles != null)
            {
                foreach (var item in roles)
                {
                    ids.Add(item.Id);
                }
            }
            user.Roles = ids.ToArray();

            var pers = adal.GetPermissions(user.RoleFlag);

            var perdata = AuthorizeProvider.PermissionMap.GetPermissionData(pers);
            user.Permissions = AuthorizeProvider.PermissionMap.PermissionsDataToBase64(perdata);
            return user;
        }



        [HttpGet]
        public string GetMd5(string value)
        {
            return Security.MD5Hash(value);
        }
    }
}
